package com.huawo.opensdk.utils;

import android.os.SystemClock;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.core.util.Supplier;

import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Single;

public class CodeWrapper {

    private static final long SPEED_LIMIT_VALUE = 500;

    public static <T> T speedLimit(boolean unlimited, @NonNull Supplier<T> supplier) {
        if (unlimited) return supplier.get();
        long st = SystemClock.elapsedRealtime();
        T result = supplier.get();
        long duration = SystemClock.elapsedRealtime() - st;
        if (duration < SPEED_LIMIT_VALUE) {
            try {
//                Log.i("CodeWrapper", "speedLimit: " + (SPEED_LIMIT_VALUE - duration));
                Thread.sleep(SPEED_LIMIT_VALUE - duration);
            } catch (Exception e) {
                Log.w("CodeWrapper", "speedLimit - Supplier: sleep", e);
            }
        }
        return result;
    }

    public static <T> Single<T> speedLimit(boolean unlimited, @NonNull Single<T> single) {
        if (unlimited) return single;
        return Single.create(emitter -> {
            try {
                long st = SystemClock.elapsedRealtime();
                T result = single.blockingGet();
                long duration = SystemClock.elapsedRealtime() - st;
                if (duration < SPEED_LIMIT_VALUE) {
                    try {
//                        Log.i("CodeWrapper", "speedLimit: " + (SPEED_LIMIT_VALUE - duration));
                        Thread.sleep(SPEED_LIMIT_VALUE - duration);
                    } catch (Exception e) {
                        Log.w("CodeWrapper", "speedLimit - Single: sleep", e);
                    }
                }
                emitter.onSuccess(result);
            } catch (Exception e) {
                emitter.onError(e);
            }
        });
    }

    public static <T> Observable<T> speedLimit(boolean unlimited, @NonNull Observable<T> observable) {
        if (unlimited) return observable;
        return Observable.create(emitter -> {
            try {
                long st = SystemClock.elapsedRealtime();
                observable.subscribe(value -> {
                    emitter.onNext(value);
                }, error -> {
                    emitter.onError(error);
                }, () -> {
                    long duration = SystemClock.elapsedRealtime() - st;
                    if (duration < SPEED_LIMIT_VALUE) {
                        try {
//                            Log.i("CodeWrapper", "speedLimit: " + (SPEED_LIMIT_VALUE - duration));
                            Thread.sleep(SPEED_LIMIT_VALUE - duration);
                        } catch (Exception e) {
                            Log.w("CodeWrapper", "speedLimit - Single: sleep", e);
                        }
                    }
                    emitter.onComplete();
                });
            } catch (Exception e) {
                emitter.onError(e);
            }
        });
    }

    public static Completable speedLimit(boolean unlimited, @NonNull Completable completable) {
        if (unlimited) return completable;
        return Completable.create(emitter -> {
            try {
                long st = SystemClock.elapsedRealtime();
                completable.blockingAwait();
                long duration = SystemClock.elapsedRealtime() - st;
                if (duration < SPEED_LIMIT_VALUE) {
                    try {
//                        Log.i("CodeWrapper", "speedLimit: " + (SPEED_LIMIT_VALUE - duration));
                        Thread.sleep(SPEED_LIMIT_VALUE - duration);
                    } catch (Exception e) {
                        Log.w("CodeWrapper", "speedLimit - Completable: sleep", e);
                    }
                }
                emitter.onComplete();
            } catch (Exception e) {
                emitter.onError(e);
            }
        });
    }

}